package com.alibaba.controller;

import com.alibaba.result.FileResult;
import com.alibaba.utils.BucketResolver;
import com.alibaba.utils.MinioUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 *
 * @author ZhouYaDong
 * @date 2025/9/23
 * @description
 */
@Slf4j
@RequestMapping("/file")
@RestController
public class FileController {

    @Resource
    private MinioUtils minioUtils;

    // 上传文件
    // 上传文件
    @PostMapping("/upload")
    public FileResult upload(@RequestParam("file") MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return FileResult.builder()
                    .code("10001")
                    .message("上传文件为空")
                    .operationType(FileResult.OperationType.UPLOAD)
                    .build();
        }

        try {
            // 获取原始文件名（确保不为 null）
            String originalFileName = file.getOriginalFilename();
            if (originalFileName == null || originalFileName.isBlank()) {
                return FileResult.builder()
                        .code("10001")
                        .message("上传文件失败：文件名为空")
                        .operationType(FileResult.OperationType.UPLOAD)
                        .build();
            }

            // **直接根据文件名解析对应的 bucket**
            String bucketName = BucketResolver.resolveBucketByFileName(originalFileName);

            // 生成唯一前缀（时间戳+随机数）
            String uniquePrefix = System.currentTimeMillis() + "-" + (int) (Math.random() * 1000);

            // 拼接新的文件名（保留原始文件名）
            String newFileName = uniquePrefix + "-" + originalFileName;

            // 获取文件扩展名（用于返回 fileType）
            String extension = "";
            int dotIndex = originalFileName.lastIndexOf('.');
            if (dotIndex > 0) {
                extension = originalFileName.substring(dotIndex + 1);
            }

            // 上传文件到 MinIO
            minioUtils.uploadFile(bucketName, file, newFileName, file.getContentType());

            // 获取文件访问 URL（预签名）
            String presignedUrl = minioUtils.getPresignedObjectUrl(bucketName, newFileName);
            log.info("文件上传成功，url: {}", presignedUrl);

            // 操作时间
            String actionTime = LocalDateTime.now()
                    .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

            // 构建返回数据
            FileResult.FileData data = FileResult.FileData.builder()
                    .fileName(newFileName)
                    .fileType(extension)
                    .bucket(bucketName)
                    .url(presignedUrl)
                    .actionTime(actionTime)
                    .build();

            return FileResult.builder()
                    .code("10000")
                    .message("文件上传成功")
                    .operationType(FileResult.OperationType.UPLOAD)
                    .data(data)
                    .build();

        } catch (Exception e) {
            log.error("文件上传失败", e);
            return FileResult.builder()
                    .code("10001")
                    .message("文件上传失败：" + e.getMessage())
                    .operationType(FileResult.OperationType.UPLOAD)
                    .build();
        }
    }



    @DeleteMapping("/delete")
    public FileResult delete(@RequestParam("fileName") String fileName) {
        String actionTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        if (fileName == null || fileName.isBlank()) {
            return fail("删除文件失败，因为 fileName 为空");
        }

        // 根据文件名自动解析桶
        String bucketName = BucketResolver.resolveBucket(getExtension(fileName));

        try {
            // 删除之前判断文件是否存在
            if (!minioUtils.isObjectExist(bucketName, fileName)) {
                return fail("删除文件失败，文件不存在");
            }

            // 删除文件
            minioUtils.removeFile(bucketName, fileName);

            // 构建返回
            FileResult.FileData data = FileResult.FileData.builder()
                    .fileName(fileName)
                    .bucket(bucketName)
                    .actionTime(actionTime)
                    .build();

            return FileResult.builder()
                    .code("10000")
                    .message("文件删除成功")
                    .operationType(FileResult.OperationType.DELETE)
                    .data(data)
                    .build();

        } catch (Exception e) {
            log.error("文件删除失败", e);
            return fail("文件删除失败：" + e.getMessage());
        }
    }

    // 文件下载
    @GetMapping("/preDownload")
    public FileResult download(@RequestParam("fileName") String fileName) {
        String actionTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        if (fileName == null || fileName.isBlank()) {
            return fail("下载文件失败，因为 fileName 为空");
        }

        // 根据文件名自动解析桶名称
        String extension = getExtension(fileName);
        String bucketName = BucketResolver.resolveBucket(extension);

        try {
            // 检查文件是否存在
            if (!minioUtils.isObjectExist(bucketName, fileName)) {
                return fail("下载文件失败，文件不存在");
            }

            // 生成预签名 URL
            String presignedUrl = minioUtils.getPresignedObjectUrl(bucketName, fileName);

            // 构建返回数据
            FileResult.FileData data = FileResult.FileData.builder()
                    .fileName(fileName)
                    .fileType(extension)
                    .bucket(bucketName)
                    .url(presignedUrl)
                    .actionTime(actionTime)
                    .build();

            return FileResult.builder()
                    .code("10000")
                    .message("文件下载成功")
                    .operationType(FileResult.OperationType.DOWNLOAD)
                    .data(data)
                    .build();
        } catch (Exception e) {
            log.error("文件下载失败", e);
            return fail("文件下载失败：" + e.getMessage());
        }
    }

    @GetMapping("/download")
    public void downloadFile(@RequestParam("fileName") String fileName,
                             HttpServletResponse response) {
        if (fileName == null || fileName.isBlank()) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }

        // 1️⃣ 根据文件名自动解析桶名称
        String extension = getExtension(fileName);
        String bucketName = BucketResolver.resolveBucket(extension);

        // 2️⃣ 下载并写入响应
        try (InputStream inputStream = minioUtils.getObject(bucketName, fileName);
             ServletOutputStream outputStream = response.getOutputStream()) {

            // 设置强制下载响应头
            response.setContentType("application/octet-stream");
            response.setHeader(
                    "Content-Disposition",
                    "attachment; filename=\"" + URLEncoder.encode(fileName, StandardCharsets.UTF_8) + "\""
            );

            // 将文件流写入响应
            byte[] buffer = new byte[8192];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            outputStream.flush();

            // 记录下载日志（可选）
            String actionTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            FileResult.FileData data = FileResult.FileData.builder()
                    .fileName(fileName)
                    .fileType(extension)
                    .bucket(bucketName)
                    .actionTime(actionTime)
                    .build();
            FileResult result = FileResult.builder()
                    .code("10000")
                    .message("文件下载成功")
                    .operationType(FileResult.OperationType.DOWNLOAD)
                    .data(data)
                    .build();
            log.info("下载记录: {}", result);

        } catch (Exception e) {
            log.error("文件下载失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }


    /** 提取文件扩展名（无点），找不到则返回空字符串 */
    private String getExtension(String fileName) {
        int index = fileName.lastIndexOf('.');
        return (index != -1 && index < fileName.length() - 1)
                ? fileName.substring(index + 1).toLowerCase()
                : "";
    }

    /** 统一失败返回 */
    private FileResult fail(String message) {
        return FileResult.builder()
                .code("10001")
                .message(message)
                .operationType(FileResult.OperationType.DELETE)
                .build();
    }




}
